﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Media;
using System.Windows;
using System.Windows.Media.Imaging;
using System.Windows.Threading;

namespace SuporeSliplampApp.Util
{
    public class CameraOpen
    {
        public static uvcham cam_ = null;
        public static WriteableBitmap bmp_ = null;
        public static IntPtr buf_ = IntPtr.Zero;
        public static DispatcherTimer timer_ = null;
        public static bool started_ = false;
        public static uint count_ = 0;
        private delegate void msg(string s);

        private int startCamera()
        {
            //Dispatcher.BeginInvoke((Action)(() =>
            //{
            //    if (cam_ != null)
            //        return;
            //    uvcham.Device[] arr = uvcham.Enum();
            //    if (arr.Length <= 0)
            //        MessageBox.Show("未找到相机");
            //    else if (1 == arr.Length)
            //        startDevice(arr[0].id);
            //}));
            if (cam_ != null)
                return (int)UIInfo.CAMSTS.Exsit;
            uvcham.Device[] arr = uvcham.Enum();
            if (arr.Length <= 0)
                return (int)UIInfo.CAMSTS.None;
            else if (1 == arr.Length)
                startDevice(arr[0].id);
            return (int)UIInfo.CAMSTS.Find;
        }

        private void startDevice(string id)
        {
            cam_ = uvcham.open(id);
            if (cam_ != null)
            {
                cam_.put(uvcham.eCMD.FORMAT, 1);
                int width = 0, height = 0, res = 0;
                cam_.get(uvcham.eCMD.RES, out res);
                cam_.get(uvcham.eCMD.WIDTH | ((uvcham.eCMD)res), out width);
                cam_.get(uvcham.eCMD.HEIGHT | ((uvcham.eCMD)res), out height);
                if ((width > 0) && (height > 0))
                {
                   // bmp_ = new WriteableBitmap(width, height, 0, 0, PixelFormats.Bgr32, null);
                    buf_ = Marshal.AllocHGlobal(uvcham.TDIBWIDTHBYTES(width * 32) * height);
                    if (cam_.start(buf_, (nEvent) =>
                    {
                        //Dispatcher.BeginInvoke((Action)(() =>
                        //{
                        //    /* this run in the UI thread */
                        //    if (cam_ != null)
                        //    {
                        //        if ((nEvent & uvcham.eEVENT.IMAGE) != 0)
                        //            OnEventImage();
                        //        else if ((nEvent & uvcham.eEVENT.ERROR) != 0)
                        //            OnEventError();
                        //        else if ((nEvent & uvcham.eEVENT.DISCONNECT) != 0)
                        //            OnEventDisconnect();
                        //    }
                        //}));
                    }) < 0)
                    {
                        MessageBox.Show("相机启动失败");
                    }
                    else
                    {
                        int nmin, nmax, ndef;
                        cam_.range(uvcham.eCMD.EXPOTIME, out nmin, out nmax, out ndef);
                        cam_.range(uvcham.eCMD.WBRED, out nmin, out nmax, out ndef);
                        cam_.range(uvcham.eCMD.WBGREEN, out nmin, out nmax, out ndef);
                        cam_.range(uvcham.eCMD.WBBLUE, out nmin, out nmax, out ndef);
                        UpdateExpoTime();
                        UpdateAwb();
                        int val = 0;
                        cam_.get(uvcham.eCMD.AEXPO, out val);
                        cam_.get(uvcham.eCMD.WBMODE, out val);
                        timer_ = new DispatcherTimer() { Interval = new TimeSpan(0, 0, 1) };
                        timer_.Tick += (object sender, EventArgs e) =>
                        {
                            if (cam_ != null)
                            {
                                UpdateExpoTime();
                                UpdateAwb();
                            }
                        };
                        timer_.Start();
                    }
                    started_ = true;
                }
            }
        }

        private void OnEventImage()
        {
            if (bmp_ != null)
            {
                try
                {
                    bmp_.Lock();
                    try
                    {
                        uvcham.memcpy(bmp_.BackBuffer, buf_, new IntPtr(uvcham.TDIBWIDTHBYTES(bmp_.PixelWidth * 32) * bmp_.PixelHeight));
                        bmp_.AddDirtyRect(new Int32Rect(0, 0, bmp_.PixelWidth, bmp_.PixelHeight));
                    }
                    finally
                    {
                        bmp_.Unlock();
                    }
                    //image_.Source = bmp_;
                }
                catch (Exception ex)
                {

                    MessageBox.Show(ex.ToString());
                }
            }
        }

        private void OnEventError()
        {
            cam_.close();
            cam_ = null;
            Marshal.FreeHGlobal(buf_);
            MessageBox.Show("Generic error");
        }

        private void OnEventDisconnect()
        {
            cam_.close();
            cam_ = null;
            Marshal.FreeHGlobal(buf_);
            MessageBox.Show("Camera disconnect");
        }

        private void UpdateExpoTime()
        {
            int val = 0;
            cam_.get(uvcham.eCMD.EXPOTIME, out val);
        }

        private void UpdateAwb()
        {
            int val = 0;
            cam_.get(uvcham.eCMD.WBRED, out val);
            cam_.get(uvcham.eCMD.WBGREEN, out val);
            cam_.get(uvcham.eCMD.WBBLUE, out val);
        }


    }

   
}
